/**
 * 
 */
package us.gaaoc.framework.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.log4j.Logger;

/**
 * @author Sukhada
 * Jun 30, 2006
 * Date Utility Class
 */
public class DateUtil {

	private static Logger LOG = Logger.getLogger(DateUtil.class);
	/**
	 * Constructor 
	 */
	private Date aocCompleteDate;
	private int aocMonth;
	private int aocDayOfMonth;
	private int aocYear;
	
	public DateUtil() {
		Locale loc = new Locale("ENGLISH", "US");
		TimeZone tz = TimeZone.getTimeZone("America/New_York");
		Calendar cal = new GregorianCalendar(tz, loc);
		
	//	Date d = cal.getTime();
		aocYear = cal.get(Calendar.YEAR);
		aocDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
		aocMonth = cal.get(Calendar.MONTH)+1;
	}
	
	public DateUtil(int month, int year, int date) {		
		this.aocMonth = month;
		this.aocDayOfMonth = date;
		this.aocYear = year;
	}
	
	/**
	 * Method to allow easy parsing of Date to be able to pull back the
	 * year, day, and month
	 * @param datePassedIn
	 */
	public DateUtil(Date datePassedIn) {
		Calendar cal = new GregorianCalendar();
		cal.setTime(datePassedIn);
		
		aocYear = cal.get(Calendar.YEAR);
		aocDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
		aocMonth = cal.get(Calendar.MONTH)+1;
		
	}

	/**
	 * This method converts the Gregorian Calendar Date to XML Gregorian Calendar Date
	 * @param date
	 * @return
	 */
	public static XMLGregorianCalendar getGivenDate( GregorianCalendar date) {
		XMLGregorianCalendar xc = null;
		//get the year from the date which is at index '1' in the array of GregorianCalendar
		int year = date.get(Calendar.YEAR);
		int month = date.get(Calendar.MONTH)+1;
		int day = date.get(Calendar.DATE);
		try {
			 xc =  DatatypeFactory.newInstance().newXMLGregorianCalendarDate(year,month,day,0);
			 }catch(DatatypeConfigurationException e) {
			 throw new Error(e);
		}
		System.out.println("XML Date : "+xc.toString());
		return xc;
	  }
	
	/**
	 * This method converts the GregorianCalendar Time to XML Gregorian Time.
	 * @param date
	 * @return
	 */
	public static XMLGregorianCalendar getGivenTime(GregorianCalendar date) {
		XMLGregorianCalendar xc = null;
		int hh = date.get(10);
		int mm = date.get(12);
		int ss = date.get(13);
		try {
			 xc =  DatatypeFactory.newInstance().newXMLGregorianCalendarTime(hh,mm,ss,0);
			 }catch(DatatypeConfigurationException e) {
			 throw new Error(e);
		}
		System.out.println("XML Time : "+xc.toString());
		return xc;
	  }
	
	/**
     * This method converts util date to sql date.
     * @param utilDate Date
     * @return Date
     */
    public static java.sql.Date utilToSqlDate(java.util.Date utilDate) {
        java.sql.Date sqlDate = null;
        if (utilDate != null) {
            sqlDate = new java.sql.Date(utilDate.getTime());
        }
        return sqlDate;
    }
   
    /**
     * This method converts GregorainCalendar date to sql date.
     * @param GregorainCalendar Date
     * @return Date
     */
    public static java.sql.Date GregorianCalendarToSqlDate(java.util.GregorianCalendar calendar) {
        java.sql.Date sqlDate = null;
        if (calendar != null) {
            sqlDate = new java.sql.Date(calendar.getTime().getTime());
        }
        return sqlDate;
    }

    /**
     * This method converts sql date to util date.
     * @param sqlDate Date
     * @return Date
     */
    public static java.util.Date sqlToUtilDate(java.sql.Date sqlDate) {
        java.util.Date utilDate = null;
        if (sqlDate != null) {
            utilDate = new java.util.Date(sqlDate.getTime());
        }
        return utilDate;
    }
    
    /**
     * This method converts a string to java.util.date.
     * @param s String
     * @return Date
     */
    public static java.util.Date convertStringToDate(String s) {
        DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM);
        java.util.Date newDate = null;
        if(s == null) return null;
        try {
            newDate = format.parse(s);
        } catch (ParseException pe) {
            LOG.info(
                    "Date Parse Exception in Base Request Message Processor Page " +
                    pe);  /* Change error to info */
        }
        return newDate;
    }
    
    /**
     * This method returns the date depending on the locale
     * @return
     */
   public static java.util.Date getCurrentDate(){
	   /*
	    * Method can be updated in the future to return a calendar if localized 
	    * time is required.  Currently, the method for time keeping is to use
	    * Greenwich Mean Time for time stamps and audit log entries.  When 
	    * displaying time in the application, then the time can be converted 
	    * back to a localized time.  
	    */
    	/* Locale loc = new Locale("ENGLISH", "US");
		TimeZone tz = TimeZone.getTimeZone("America/New_York");
		Calendar cal = new GregorianCalendar(tz, loc); */
		Date dt = new Date();
		//LOG.debug("Calendar: " + cal.toString() + "\n\n\n Date: " + dt.toString());		
    	return dt;
    }
   
   /**
    * Method to get conditional date based on rules supplied by the Court.  
    * 
    * Useful for situations such as when the court limits receiving filings to 
    * business hours.
    * 
    * @param courtUuid - UUID of the Court whose rules will be used.
    * @return Date based on the conditions of the Court's rules.
    */
   public static Date getConditionalCurrentDate(String courtUuid){
	   // TODO Need to make this method dynamic and configured based on settings
	   // stored in the database.
	   Date targetDate = new Date();
	   if (courtUuid.equals("courtUuidBibb")) {
		   Locale loc = new Locale("ENGLISH", "US");
		   TimeZone tz = TimeZone.getTimeZone("America/New_York");
		   Calendar cal = new GregorianCalendar(tz, loc);
		   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
		   boolean dateChanged = false; 
		   
		   // See if need to change date
		   
		   // If after 3 pm . . .
		   if (cal.get(Calendar.HOUR_OF_DAY) >= 15 ) {
			   // and on a Friday, then move the date to the next Monday.
			   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
				   newDayOfMonth += 3; // Increment it by 3
			   // and on a Saturday, then move the date to the next Monday.
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
				   newDayOfMonth += 2; // Increment it by 2
			   // and on a day Sunday through Thursday, move the date to the
			   // next day.
			   } else {
				   newDayOfMonth += 1; // Increment it by 1
			   }
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
			   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
			   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
		   } else {
			   return targetDate;
		   }
		   // If date changed, modify the time of the filing to 1:00AM
		   // and use the new date for the "Court Received Date"
		   if (dateChanged) {
			// Set the time to the next day at 1:00 AM
			   cal.set(Calendar.DATE, newDayOfMonth);
			   cal.set(Calendar.HOUR_OF_DAY, 1);
			   cal.set(Calendar.MINUTE, 0);
			   targetDate = cal.getTime();
		   }
		   
	   } else if (courtUuid.equalsIgnoreCase("courtUuid2")) {

		   Locale loc = new Locale("ENGLISH", "US");
		   TimeZone tz = TimeZone.getTimeZone("America/New_York");
		   Calendar cal = new GregorianCalendar(tz, loc);
		   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
		   boolean dateChanged = false; 
		   
		   // If after 5 pm . . .
		   if (cal.get(Calendar.HOUR_OF_DAY) >= 17 ) {
			   // and on a Friday, then move the date to the next Monday.
			   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
				   newDayOfMonth += 3; // Increment it by 3
			   // and on a Saturday, then move the date to the next Monday.
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
				   newDayOfMonth += 2; // Increment it by 2
			   // and on a day Sunday through Thursday, move the date to the
			   // next day.
			   } else {
				   newDayOfMonth += 1; // Increment it by 1
			   }
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
			   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
			   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
		   } else {
			   return targetDate;
		   }
		   // If date changed, modify the time of the filing to 1:00AM
		   // and use the new date for the "Court Received Date"
		   if (dateChanged) {
			// Set the time to the next day at 1:00 AM
			   cal.set(Calendar.DATE, newDayOfMonth);
			   cal.set(Calendar.HOUR_OF_DAY, 1);
			   cal.set(Calendar.MINUTE, 0);
			   targetDate = cal.getTime();
		   }
	   }else if(courtUuid.equalsIgnoreCase("courtUuid3"))
	   {
		   
	   	//TODO: verify these date assumptions.
		   /*
		   Locale loc = new Locale("ENGLISH", "US");
		   TimeZone tz = TimeZone.getTimeZone("America/New_York");
		   Calendar cal = new GregorianCalendar(tz, loc);
		   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
		   boolean dateChanged = false; 
		   
		   // See if need to change date
		   
		   // If after 3 pm . . .
		   if (cal.get(Calendar.HOUR_OF_DAY) >= 15 ) {
			   // and on a Friday, then move the date to the next Monday.
			   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
				   newDayOfMonth += 3; // Increment it by 3
			   // and on a Saturday, then move the date to the next Monday.
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
				   newDayOfMonth += 2; // Increment it by 2
			   // and on a day Sunday through Thursday, move the date to the
			   // next day.
			   } else {
				   newDayOfMonth += 1; // Increment it by 1
			   }
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
			   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
			   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
		   } else {
			   return targetDate;
		   }
		   // If date changed, modify the time of the filing to 1:00AM
		   // and use the new date for the "Court Received Date"
		   if (dateChanged) {
			// Set the time to the next day at 1:00 AM
			   cal.set(Calendar.DATE, newDayOfMonth);
			   cal.set(Calendar.HOUR_OF_DAY, 1);
			   cal.set(Calendar.MINUTE, 0);
			   targetDate = cal.getTime();
		   }
		   */
	   }else if (courtUuid.equalsIgnoreCase("courtUuidHart"))
	   {
			   Locale loc = new Locale("ENGLISH", "US");
			   TimeZone tz = TimeZone.getTimeZone("America/New_York");
			   Calendar cal = new GregorianCalendar(tz, loc);
			   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
			   boolean dateChanged = false; 
			   
			   // See if need to change date
			   
			   // If after 3 pm . . .
			   if (cal.get(Calendar.HOUR_OF_DAY) >= 15 ) {
				   // and on a Friday, then move the date to the next Monday.
				   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
					   newDayOfMonth += 3; // Increment it by 3
				   // and on a Saturday, then move the date to the next Monday.
				   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
					   newDayOfMonth += 2; // Increment it by 2
				   // and on a day Sunday through Thursday, move the date to the
				   // next day.
				   } else {
					   newDayOfMonth += 1; // Increment it by 1
				   }
				   dateChanged = true;
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
				   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
				   dateChanged = true;
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
				   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
			   } else {
				   return targetDate;
			   }
			   // If date changed, modify the time of the filing to 1:00AM
			   // and use the new date for the "Court Received Date"
			   if (dateChanged) {
				// Set the time to the next day at 1:00 AM
				   cal.set(Calendar.DATE, newDayOfMonth);
				   cal.set(Calendar.HOUR_OF_DAY, 1);
				   cal.set(Calendar.MINUTE, 0);
				   targetDate = cal.getTime();
			   }
			   
	   }else if (courtUuid.equalsIgnoreCase("courtUuidJefferson"))
	   {
		   Locale loc = new Locale("ENGLISH", "US");
		   TimeZone tz = TimeZone.getTimeZone("America/New_York");
		   Calendar cal = new GregorianCalendar(tz, loc);
		   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
		   boolean dateChanged = false; 
		   
		   // See if need to change date
		   
		   // If after 3 pm . . .
		   if (cal.get(Calendar.HOUR_OF_DAY) >= 15 ) {
			   // and on a Friday, then move the date to the next Monday.
			   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
				   newDayOfMonth += 3; // Increment it by 3
			   // and on a Saturday, then move the date to the next Monday.
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
				   newDayOfMonth += 2; // Increment it by 2
			   // and on a day Sunday through Thursday, move the date to the
			   // next day.
			   } else {
				   newDayOfMonth += 1; // Increment it by 1
			   }
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
			   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
			   dateChanged = true;
		   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
			   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
		   } else {
			   return targetDate;
		   }
		   // If date changed, modify the time of the filing to 1:00AM
		   // and use the new date for the "Court Received Date"
		   if (dateChanged) {
			// Set the time to the next day at 1:00 AM
			   cal.set(Calendar.DATE, newDayOfMonth);
			   cal.set(Calendar.HOUR_OF_DAY, 1);
			   cal.set(Calendar.MINUTE, 0);
			   targetDate = cal.getTime();
		   }
	   }else if(courtUuid.equalsIgnoreCase("courtUuid5")) //For Oglethorpe County
		   {
		   	//TODO: verify these date assumptions.
			   Locale loc = new Locale("ENGLISH", "US");
			   TimeZone tz = TimeZone.getTimeZone("America/New_York");
			   Calendar cal = new GregorianCalendar(tz, loc);
			   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
			   boolean dateChanged = false; 
			   
			   // See if need to change date
			   
			   // If after 3 pm . . .
			   if (cal.get(Calendar.HOUR_OF_DAY) >= 17 ) {
				   // and on a Friday, then move the date to the next Monday.
				   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
					   newDayOfMonth += 3; // Increment it by 3
				   // and on a Saturday, then move the date to the next Monday.
				   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
					   newDayOfMonth += 2; // Increment it by 2
				   // and on a day Sunday through Thursday, move the date to the
				   // next day.
				   } else {
					   newDayOfMonth += 1; // Increment it by 1
				   }
				   dateChanged = true;
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
				   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
				   dateChanged = true;
			   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
				   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
			   } else {
				   return targetDate;
			   }
			   // If date changed, modify the time of the filing to 1:00AM
			   // and use the new date for the "Court Received Date"
			   if (dateChanged) {
				// Set the time to the next day at 1:00 AM
				   cal.set(Calendar.DATE, newDayOfMonth);
				   cal.set(Calendar.HOUR_OF_DAY, 1);
				   cal.set(Calendar.MINUTE, 0);
				   targetDate = cal.getTime();
			   }
		   }else if(courtUuid.equalsIgnoreCase("courtUuidLee")) //For Lee County
		   {
			   	//TODO: verify these date assumptions.
				   Locale loc = new Locale("ENGLISH", "US");
				   TimeZone tz = TimeZone.getTimeZone("America/New_York");
				   Calendar cal = new GregorianCalendar(tz, loc);
				   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
				   boolean dateChanged = false; 
				   
				   // See if need to change date
				   
				   // If after 3 pm . . .
				   if (cal.get(Calendar.HOUR_OF_DAY) >= 17 ) {
					   // and on a Friday, then move the date to the next Monday.
					   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
						   newDayOfMonth += 3; // Increment it by 3
					   // and on a Saturday, then move the date to the next Monday.
					   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
						   newDayOfMonth += 2; // Increment it by 2
					   // and on a day Sunday through Thursday, move the date to the
					   // next day.
					   } else {
						   newDayOfMonth += 1; // Increment it by 1
					   }
					   dateChanged = true;
				   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
					   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
					   dateChanged = true;
				   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
					   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
				   } else {
					   return targetDate;
				   }
				   // If date changed, modify the time of the filing to 1:00AM
				   // and use the new date for the "Court Received Date"
				   if (dateChanged) {
					// Set the time to the next day at 1:00 AM
					   cal.set(Calendar.DATE, newDayOfMonth);
					   cal.set(Calendar.HOUR_OF_DAY, 1);
					   cal.set(Calendar.MINUTE, 0);
					   targetDate = cal.getTime();
				   }
			   } else if(courtUuid.equalsIgnoreCase("courtUuid4")) //For Fulton County
			   {
				   	//TODO: verify these date assumptions.
					   Locale loc = new Locale("ENGLISH", "US");
					   TimeZone tz = TimeZone.getTimeZone("America/New_York");
					   Calendar cal = new GregorianCalendar(tz, loc);
					   int newDayOfMonth = cal.get(Calendar.DATE); // Get Current Date
					   boolean dateChanged = false; 
					   
					   // See if need to change date
					   
					   // If after 11:59 pm . . .
					   if (cal.get(Calendar.HOUR_OF_DAY) >= 23 ) {
						   // and on a Friday, then move the date to the next Monday.
						   if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
							   newDayOfMonth += 3; // Increment it by 3
						   // and on a Saturday, then move the date to the next Monday.
						   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
							   newDayOfMonth += 2; // Increment it by 2
						   // and on a day Sunday through Thursday, move the date to the
						   // next day.
						   } else {
							   newDayOfMonth += 1; // Increment it by 1
						   }
						   dateChanged = true;
					   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
						   newDayOfMonth += 2; // Increment it by 2 to fall on Monday
						   dateChanged = true;
					   } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
						   newDayOfMonth += 1; // Increment it by 1 to fall on Monday
					   } else {
						   return targetDate;
					   }
					   // If date changed, modify the time of the filing to 1:00AM
					   // and use the new date for the "Court Received Date"
					   if (dateChanged) {
						// Set the time to the next day at 1:00 AM
						   cal.set(Calendar.DATE, newDayOfMonth);
						   cal.set(Calendar.HOUR_OF_DAY, 1);
						   cal.set(Calendar.MINUTE, 0);
						   targetDate = cal.getTime();
					   }
				   } else{
			   
		   }
	   return targetDate;
   }

	public Date getAocCompleteDate() {
		return aocCompleteDate;
	}

	public void setAocCompleteDate(Date aocCompleteDate) {
		this.aocCompleteDate = aocCompleteDate;
	}

	public int getAocDayOfMonth() {
		return aocDayOfMonth;
	}

	public void setAocDayOfMonth(int aocDate) {
		this.aocDayOfMonth = aocDate;
	}

	public int getAocMonth() {
		return aocMonth;
	}

	public void setAocMonth(int aocMonth) {
		this.aocMonth = aocMonth;
	}

	public int getAocYear() {
		return aocYear;
	}

	public void setAocYear(int aocYear) {
		this.aocYear = aocYear;
	}
	
	/**
	 * Method to change numerical date for month to a the word for the name
	 * of the month.
	 * @param monthPassedIn Number for for the date of the month
	 * @return String representing the name of the month
	 */
	public static String changeMonthFromNumberToWord(String monthPassedIn) {
		String month = monthPassedIn;
		//	Change Month expression from number to word
		if (month.equalsIgnoreCase("1"))
			month = "January";
		if (month.equalsIgnoreCase("2"))
			month = "February";
		if (month.equalsIgnoreCase("3"))
			month = "March";
		if (month.equalsIgnoreCase("4"))
			month = "April";
		if (month.equalsIgnoreCase("5"))
			month = "May";
		if (month.equalsIgnoreCase("6"))
			month = "June";
		if (month.equalsIgnoreCase("7"))
			month = "July";
		if (month.equalsIgnoreCase("8"))
			month = "August";
		if (month.equalsIgnoreCase("9"))
			month = "September";
		if (month.equalsIgnoreCase("10"))
			month = "October";
		if (month.equalsIgnoreCase("11"))
			month = "November";
		if (month.equalsIgnoreCase("12"))
			month = "December";
		
		return month;
	}
	
   
}
